package com.lin.server.impl;

import com.lin.dataobject.Product;
import com.lin.dataobject.ProductAttributeValue;
import com.lin.dto.NewProductDTO;
import com.lin.repository.ProductAttributeValueRepository;
import com.lin.repository.ProductRepository;
import com.lin.server.ProductService;
import com.lin.utils.DateUtils;
import com.lin.utils.KeyUtils;
import com.lin.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2017-10-20.
 */
@Service
public class ProductServerImpl implements ProductService{

    @Autowired
    private ProductRepository repository;

    @Autowired
    private ProductAttributeValueRepository productAttributeValueRepository;

    @Autowired
    private ProductAttributeValueRepository valueRepository;

    @Override
    public Product findOne(String id) {
        return repository.findOne(id);
    }

    @Override
    public List<Product> findAll(String id, String name, String category, String startTime, String endTime) {
        return repository.findAll(getSpecification(id,name,category,startTime,endTime));
    }

    @Override
    public Page<Product> findAll(String id, String name, String category, String startTime, String endTime, Pageable pageable) {
        return repository.findAll(getSpecification(id,name,category,startTime,endTime),pageable);
    }

    @Override
    public Product save(Product product) {
        return repository.save(product);
    }

    @Override
    @Transactional
    public void del(String productId) {
        repository.delete(productId);
        productAttributeValueRepository.deleteProductAttributeValuesByProductId(productId);
    }

    @Override
    public Long getSize(String id, String name, String category, String startTime, String endTime) {
        return repository.count(getSpecification(id,name,category,startTime,endTime));
    }

    private Specification<Product> getSpecification(String id, String name, String category, String startTime, String endTime){
        return new Specification<Product>() {
            @Override
            public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates=new ArrayList<>();
                if (StringUtils.isNotEmpty(id)){
                    predicates.add(criteriaBuilder.like(root.get("id"),"%"+id+"%"));
                }
                if (StringUtils.isNotEmpty(startTime)){
                    Date start= DateUtils.stringToDate(startTime);
                    predicates.add(criteriaBuilder.greaterThan(root.get("createTime"),start));
                }
                if (StringUtils.isNotEmpty(endTime)){
                    Date end=DateUtils.addDay(endTime,1);
                    predicates.add(criteriaBuilder.lessThan(root.get("createTime"),end));
                }
                if (StringUtils.isNotEmpty(name)){
                    predicates.add(criteriaBuilder.like(root.get("name"),"%"+name+"%"));
                }
                if (StringUtils.isNotEmpty(category)){
                    predicates.add(criteriaBuilder.equal(root.get("category"),Integer.valueOf(category)));
                }
                return criteriaQuery.where(predicates.toArray
                        (new Predicate[predicates.size()])).getRestriction();
            }
        };
    }

    @Override
    public NewProductDTO save(NewProductDTO newProductDTO) {
        String id= KeyUtils.getUniqueKey();
        for (ProductAttributeValue value:newProductDTO.getList()) {
            value.setProductId(id);
            valueRepository.save(value);
        }
        Product product=new Product();
        newProductDTO.setId(id);
        BeanUtils.copyProperties(newProductDTO,product);
        repository.save(product);
        return newProductDTO;
    }

    @Override
    public List<ProductAttributeValue> findAttributeByProduct(String productId) {
        return productAttributeValueRepository.findByProductId(productId);
    }

    @Override
    public NewProductDTO update(NewProductDTO newProductDTO) {
        List<ProductAttributeValue> oldValueList=productAttributeValueRepository.findByProductId(newProductDTO.getId());
        List<ProductAttributeValue> newValueList=newProductDTO.getList();
        if (newValueList!=null&&newValueList.size()>0){
            for (ProductAttributeValue oldValue:oldValueList){
                boolean isUpdate=false;
                for (ProductAttributeValue newValue:newValueList){
                    if (oldValue.getId().equals(newValue.getId())){
                        newValue.setProductId(oldValue.getProductId());
//                        BeanUtils.copyProperties(newValue,oldValue);
                        productAttributeValueRepository.save(newValue);
                        isUpdate=true;
                        break;
                    }
                }
                if (!isUpdate){
                    productAttributeValueRepository.delete(oldValue);
                }
            }

            for (ProductAttributeValue value:newValueList){
                if (StringUtils.isEmpty(value.getId())){
                    value.setProductId(newProductDTO.getId());
                    productAttributeValueRepository.save(value);
                }
            }

        }
        Product product=new Product();
        BeanUtils.copyProperties(newProductDTO,product);
        repository.save(product);
        return newProductDTO;
    }
}
